const sqlite3 = require("sqlite3").verbose();
// const path = require("path");
const upgradeToV3 = require("./migrations/migration_v3.js");
// const userDataPath = require('electron').app.getPath('userData');
// const dbPath = path.join(userDataPath, 'userUploadDownload.db');

// const dbPath = path.join(__dirname, "userUploadDownload.db");
const currentVersion = 3;
let isDatabaseClosed = false;
let databaseInstance = null;
let databasePath;

const getDbInstance = ({ dbPath, isNotFoundCreate = true } = {}) => {
  if (!isNotFoundCreate) {
    return databaseInstance;
  }

  if (databaseInstance) {
    return databaseInstance;
  }

  if (dbPath) {
    databasePath = dbPath;
  }

  if (!databasePath) {
    throw new Error({ message: "databasePath is empty" });
  }

  databaseInstance = new sqlite3.Database(databasePath, (err) => {
    if (err) {
      console.error("Failed to connect to the database:", err);
    } else {
      console.log("Connected to the database");
    }
  });
  return databaseInstance;
};

const upgradeDatabase = (db, oldVersion, newVersion) => {
  if (!db) {
    console.error("upgradeDatabase db is empty");
    return;
  }
  db.serialize(() => {
    try {
      if (oldVersion < 3) {
        upgradeToV3(db, (err) => {
          if (err) {
            console.error("Failed to upgrade database:", err);
            console.error("Rolling back changes");
          } else {
            console.log("Database upgraded successfully");

            // 更新版本信息
            db.run(
              "UPDATE version SET version = ?",
              newVersion,
              (updateErr) => {
                if (updateErr) {
                  console.error(
                    "Failed to update database version:",
                    updateErr
                  );
                } else {
                  console.log(`Database version updated to ${newVersion}`);
                }
              }
            );
          }
        });
      }
    } catch (error) {
      console.error("[upgradeDatabase error]", error);
    }

    // 在这里添加其他升级操作
  });
};

const initDatabase = (db, callback = () => {}) => {
  if (!db) {
    console.error("initDatabase db is empty");
    return callback("db is empty");
  }
  db.serialize(() => {
    try {
      // 创建 uploads 表（如果不存在）
      db.run(`
        CREATE TABLE IF NOT EXISTS uploads (
          taskid INTEGER PRIMARY KEY,
          userid TEXT,
          status INTEGER,
          fileName TEXT,
          fileSize INTEGER,
          filePath TEXT,
          fileOwner TEXT,
          fileRemotePath TEXT,
          fileMimeType TEXT,
          fileType TEXT,
          progress INTEGER,
          uploadDate INTEGER,
          completedDate INTEGER,
          groupDeviceId TEXT,
          syKeyDid TEXT,
          syKeyInitString TEXT,
          syKeyApiLicenses TEXT,
          syKeyCrcKey TEXT,
          playload BLOB,
          code INTEGER
        )
        `);

      // 创建 downloads 表（如果不存在）
      db.run(`
        CREATE TABLE IF NOT EXISTS downloads (
        taskid INTEGER PRIMARY KEY,
        userid TEXT,
        status INTEGER,
        fileName TEXT,
        fileSize INTEGER,
        filePath TEXT,
        fileOwner TEXT,
        fileRemotePath TEXT,
        fileMimeType TEXT,
        fileType TEXT,
        progress INTEGER,
        localDirectory TEXT,
        downloadDate INTEGER,
        completedDate INTEGER,
        groupDeviceId TEXT,
        deviceId TEXT,
        hostname TEXT,
        syKeyDid TEXT,
        syKeyInitString TEXT,
        syKeyApiLicenses TEXT,
        syKeyCrcKey TEXT,
        playload BLOB,
        code INTEGER
        )
        `);

      // 在文件表（uploads/downloads）上创建一个索引，以提高查询性能
      // 在 "uploads" 表的 "status" 列上创建索引。
      // 索引有助于提高基于 "status" 列的查询性能。当我们需要按照上传任务的状态
      // 快速检索时，这个索引将显得非常有用。
      db.run(
        "CREATE INDEX IF NOT EXISTS uploads_status_index ON uploads (status)"
      );

      // 在 "downloads" 表的 "status" 列上创建索引。
      // 和上面的 "uploads" 表类似，此索引旨在加快基于 "status" 列的查询速度，
      // 使我们能够迅速检索按下载状态排序的任务。
      db.run(
        "CREATE INDEX IF NOT EXISTS downloads_status_index ON downloads (status)"
      );

      // 在 "downloads" 表的 "taskid" 列上创建索引。
      // 这个索引有助于我们快速地按任务ID检索下载任务。
      // 对于需要按唯一任务ID查找具体下载任务的操作，此索引将显得非常有用。
      db.run(
        "CREATE INDEX IF NOT EXISTS downloads_taskid_index ON downloads (taskid)"
      );

      // 在 "downloads" 表的 "userid" 列上创建索引。
      // 此索引旨在提高基于用户ID的查询性能，这对于查找特定用户的所有下载任务来说是非常有用的。
      db.run(
        "CREATE INDEX IF NOT EXISTS downloads_userid_index ON downloads (userid)"
      );

      // 在 "downloads" 表的 "groupDeviceId" 列上创建索引。
      // 这个索引有助于我们按组设备ID快速检索下载任务。
      // 当我们需要查询某个设备组中的所有下载任务时，此索引将提供显著的性能优势。
      db.run(
        "CREATE INDEX IF NOT EXISTS downloads_groupDeviceId_index ON downloads (groupDeviceId)"
      );

      // https://blog.51cto.com/u_15147537/5935247
      // 设置 SQLite 的日志模式为 Write-Ahead Logging (WAL)。
      // WAL 模式允许并发的读和写，提高了多线程环境下的数据库性能。
      db.run("PRAGMA journal_mode=WAL;");

      // 设置 WAL 文件的大小限制为 10MB。
      // 当 WAL 文件大小达到或超过此限制时，SQLite 会尝试执行检查点操作，
      // 将 WAL 文件中的更改合并回主数据库文件，并重置 WAL 文件的大小。
      // 这有助于确保 WAL 文件不会无限制地增长，从而占用大量的磁盘空间。
      db.run("PRAGMA journal_size_limit=10485760;"); // 10MB = 10 x 1024 x 1024 bytes = 10,485,760 bytes

      // 设置触发自动检查点的 WAL 文件页数为 200。
      // 默认情况下，此值是 1000。自动检查点意味着当 WAL 文件的页数达到此设定值时，
      // SQLite 会自动将这些更改合并回主数据库文件。
      // 通过降低此值，我们可以确保更频繁地执行检查点操作，但可能牺牲一些写入性能。
      db.run("PRAGMA wal_autocheckpoint=200;"); // 默认是1000，这里改成200

      // 关闭 SQLite 的同步写入。
      // 这可以提高写入性能，因为它不会每次都等待数据写入磁盘。
      // 但这也增加了在系统崩溃或断电时数据损坏的风险。
      db.run("PRAGMA synchronous = OFF"); // 调整写入同步设置

      // 设置 SQLite 的内存缓存大小为 10,000 页。
      // 默认情况下，每页大小为 1.5 KB，因此这相当于约 15 MB 的缓存。
      // 增加缓存大小可以提高数据库的读取性能，但也会增加应用程序的内存使用。
      db.run("PRAGMA cache_size = 10000"); // 使用更大的缓存大小 15 MB 的内存

      // 创建 version 表（如果不存在）
      db.run("CREATE TABLE IF NOT EXISTS version (version INTEGER)");

      // 获取当前数据库版本
      db.get("SELECT version FROM version", (err, row) => {
        if (err || !row) {
          // 如果表为空，插入当前版本
          db.run("INSERT INTO version (version) VALUES (?)", currentVersion);
        } else {
          console.log("db row.version", row.version);
          console.log("db currentVersion", currentVersion);
          // 如果当前版本高于数据库版本，执行升级操作
          if (currentVersion > row.version) {
            upgradeDatabase(row.version, currentVersion);
          }
        }
      });

      callback();
    } catch (error) {
      console.error("[main/sqlite initDatabase error]", error.message);
      callback(error);
    }
  });
};
const closeDatabase = (db, callback = () => {}) => {
  if (!db) {
    console.error("upgradeDatabase db is empty");
    return callback("db is empty");
  }
  if (isDatabaseClosed) {
    console.warn("Database is already closed.");
    return callback(null); // 如果数据库已关闭，直接回调
  }
  db.close((err) => {
    isDatabaseClosed = true;
    dbInstance = null;
    if (err) {
      console.error("Error closing the database:", err);
      callback(err);
    } else {
      console.log("Database closed successfully");
      callback(null);
    }
  });
};

module.exports = {
  getDbInstance,
  initDatabase,
  upgradeDatabase,
  closeDatabase,
};
